def func1():
    """
    海象操作符
    强调count是针对if使用的
    有点类似于golang
    if count := 100; count >= 20{xxxx}
    但是这个 操作符 集 赋值+使用 于一身
    省去了步骤
    """
    if count := 100:
        print(100)
    if count := 20 >= 4:
        print(200)


def func2():
    """
    星号表达式
    捕获对应剩余位置的元素，如果已经没有剩余元素，则为空
    """
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    o, p, *q = a
    print(f"o: {o}, p: {p}, q: {q}")
    o, *p, q = a
    print(f"o: {o}, p: {p}, q: {q}")
    *o, p, q = a
    print(f"o: {o}, p: {p}, q: {q}")

    data = {
        "name": ["lihua", "zhangsan", "xiaoming", "xiaohua"],
        "sex": [1, 0, 0, 0]
    }
    # 不推荐这样使用
    (
        (key1, (value1, *value2)),
        (key2, (value3, *value4))
    ) = data.items()
    print(f"key1: {key1}, value1: {value1}, value2: {value2}")
    print(f"key2: {key2}, value3: {value3}, value4: {value4}")


class Man:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Man(name={self.name}, age={self.age})"


def func3():
    """
    sort 按指定key排序
    """
    import random
    man_list = [Man(name=f"a_{n}", age=random.randint(1, 10)) for n in range(10)]
    print("before")
    print(man_list)
    # man_list.sort()  # 报错
    n1 = sorted(man_list, key=lambda x: x.age)
    print("after")
    print(n1)
    # 元祖 两个字段升序
    n2 = sorted(man_list, key=lambda x: (x.age, x.name))
    print(f"n2: {n2}")
    # 如果有数字，可以通过加上“-”达到取相反数，从而实现倒序
    n3 = sorted(man_list, key=lambda x: (-x.age, x.name))
    print(f"n3: {n3}")


def concat_value(value):
    print(f"concat_value: {value}")
    return f"v_{value}"


def func4():
    """
    setdefault的使用
    Python 的函数参数在调用时必须先求值，因此 default 表达式会在调用前被计算
    也就是说 setdefault(key, value)
    即便key存在，也会先把default创建出来
    如果value是列表之类的，就会导致产生较大的性能开销
    :return:
    """
    md = {
        "name": ["lihua", "zhangsan", "xiaohua"],
        "sex": [1, 0, 0, 0]
    }
    value = set()

    # 如果不存在这个值，设置一个，并设置value
    # value是直接放到字典里的，而不是副本
    # 且返回当前key的value
    result = md.setdefault("age", value)
    value.add(10)
    value.add(12)
    print(result)
    print(md)
    md.setdefault("age", concat_value("123456"))
    print(result)
    print(md)


def func5():
    """
    defaultdict的使用
    如果不存在直接创建
    :return:
    """
    from collections import defaultdict
    md = defaultdict(set)
    md["name"].add("lihua")
    md["name"].add("zhangsan")
    md["age"].add(1)
    md["age"].add(2)
    print(md)


def open_picture(path: str):
    try:
        return open(path, mode="r", encoding="utf-8")
    except OSError:
        print(f"Failed to open {path}")
        raise


class Pictures(dict):
    def __missing__(self, key):
        """
        result = pictures[key]
        如果key不存在，执行该逻辑
        :param key:
        :return:
        """
        value = open_picture(key)
        self[key] = value
        return value


def func6():
    """
    dict
    默认key不存在就会报错
    通过设置__missing__对不存在的key做处理
    :return:
    """
    pictures = Pictures()
    handle = pictures["1-format.py"]
    handle.seek(0)
    data = handle.read()
    print(data)


if __name__ == '__main__':
    func6()
